package nio.socket;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Iterator;
import java.util.Scanner;

/**
 * @program JavaBase
 * @description: 非阻塞式网络通讯
 * @author: zhanglu
 * @create: 2019-11-22 11:36:00
 */
public class NoBlockingNio {

    public static void main(String[] args) throws Exception {

        client();
    }

    public static void client() throws Exception {
        SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 8989));

        //切换为非阻塞模式
        socketChannel.configureBlocking(false);

        ByteBuffer buf = ByteBuffer.allocate(1024);

        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()){
            String next = scanner.next();
            String str = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + "：" + next;
            buf.put(str.getBytes());
            buf.flip();
            socketChannel.write(buf);
            buf.clear();
        }

        socketChannel.close();
    }



}

class Server{

    public static void main(String[] args) throws IOException {
        server();
    }

    public static void server() throws IOException {
        ServerSocketChannel socketChannel = ServerSocketChannel.open();

        socketChannel.configureBlocking(false);

        socketChannel.bind(new InetSocketAddress(8989));

        //获取选择器
        Selector selector = Selector.open();

        //将通道注册到选择器上，并且指定 监听接收事件
        /*
            读 写 连接 接收
         */
        socketChannel.register(selector, SelectionKey.OP_ACCEPT);

        //轮巡式的获取选择器上已经准备就绪的事件
        while (selector.select() > 0){
            //获取当前选择器中所有注册的选择键(已就绪的监听事件)
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();

            while(iterator.hasNext()){
                SelectionKey sk = iterator.next();

                //判断具体是什么事件的准备就绪
                if(sk.isAcceptable()){
                    //若 接收就绪 获取客户端连接
                    SocketChannel accept = socketChannel.accept();
                    accept.configureBlocking(false);
                    //将通道注册到选择器上
                    accept.register(selector, SelectionKey.OP_READ);
                }else if(sk.isReadable()){
                    //若 读就绪 ，获取当前选择器上的 读就绪 通道
                    SocketChannel channel = (SocketChannel) sk.channel();
                    //读取数据
                    ByteBuffer buf = ByteBuffer.allocate(1024);
                    int len = -1;
                    while ((len = channel.read(buf)) != -1){
                        buf.flip();
                        System.out.println(new String(buf.array(), 0, len));
                        buf.clear();
                    }
                }
            }
            //取消选择键
            iterator.remove();
        }

    }
}